<?php

//https://packagist.org/packages/react/async
require '../vendor/autoload.php';

use function React\Async\async;
use function React\Async\delay;
use function React\Async\waterfall;
use React\EventLoop\Loop;
use React\Promise\Promise;
use function React\Promise\resolve;


function start()
{
    React\Async\parallel([
        function () {
            return new Promise(function ($resolve) {
                Loop::addTimer(3, function () use ($resolve) {
                    $resolve('Slept for a whole second');
                });
            });
        },
        function () {
            return new Promise(function ($resolve) {
                Loop::addTimer(3, function () use ($resolve) {
                    $resolve('Slept for another whole second');
                });
            });
        },
        function () {
            return new Promise(function ($resolve) {
                Loop::addTimer(3, function () use ($resolve) {
                    $resolve('Slept for yet another whole second');
                });
            });
        },
    ])->then(function (array $results) {
        foreach ($results as $result) {
            var_dump($result);
        }
    }, function (Exception $e) {
        echo 'Error: ' . $e->getMessage() . PHP_EOL;
    });
}

function start2()
{
    $addOne = function ($prev = 0) {
        return new Promise(function ($resolve) use ($prev) {
            Loop::addTimer(1, function () use ($prev, $resolve) {
                $resolve($prev + 1);
            });
        });
    };

    React\Async\waterfall([
        $addOne,
        $addOne,
        $addOne
    ])->then(function ($prev) {
        echo "Final result is $prev\n";
    }, function (Exception $e) {
        echo 'Error: ' . $e->getMessage() . PHP_EOL;
    });
}

function start3()
{
    React\Async\series([
        function () {
            return new Promise(function ($resolve) {
                Loop::addTimer(1, function () use ($resolve) {
                    $resolve('Slept for a whole second');
                });
            });
        },
        function () {
            return new Promise(function ($resolve) {
                Loop::addTimer(1, function () use ($resolve) {
                    $resolve('Slept for another whole second');
                });
            });
        },
        function () {
            return new Promise(function ($resolve) {
                Loop::addTimer(1, function () use ($resolve) {
                    $resolve('Slept for yet another whole second');
                });
            });
        },
    ])->then(function (array $results) {
        foreach ($results as $result) {
            var_dump($result);
        }
    }, function (Exception $e) {
        echo 'Error: ' . $e->getMessage() . PHP_EOL;
    });
}

function someAsyncOperation()
{
    $resolver = function (callable $resolve, callable $reject) {
        // Do some work, possibly asynchronously, and then
        // resolve or reject.

        Loop::addTimer(3, function () use ($resolve) {
            $resolve(rand(100, 999));
        });

        // or throw new Exception('Promise rejected');
        // or $resolve($anotherPromise);
        // or $reject($nastyError);
    };

    $canceller = function () {
        // Cancel/abort any running operations like network connections, streams etc.

        // Reject promise by throwing an exception
        throw new Exception('Promise cancelled');
    };
    $promise = new React\Promise\Promise($resolver, $canceller);

    return $promise;
}


function start4()
{
    Loop::futureTick(function () {
        someAsyncOperation()->then(function ($result) {
            var_dump($result);
        });
    });

    Loop::futureTick(function () {
        someAsyncOperation()->then(function ($result) {
            var_dump($result);
        });
    });

    Loop::futureTick(function () {
        someAsyncOperation()->then(function ($result) {
            var_dump($result);
        });
    });


}


//start();
//start2();
//start3();
//start4();


